package Singleton;

//双重检查锁，解决懒汉式单例线程不安全问题
public class DoubleCheckSingleton {
    private volatile static  DoubleCheckSingleton instance;//第二层锁，volatile关键字禁止指令重排

    private DoubleCheckSingleton(){ }

    public static DoubleCheckSingleton getInstance(){
            if(instance==null){//第一层检查，检查是否有引用指向对象，高并发情况下会有多个线程同时进入
                synchronized (DoubleCheckSingleton.class) {//第一层锁，保证只有一个线程进入
                    //双重检查，防止多个线程同时进入第一层检查(因单例模式只允许存在一个对象，故在创建对象之前无引用指向对象，所有线程均可进入第一层检查)
                    //当某一线程获得锁创建一个Singleton对象时,即已有引用指向对象，singleton不为空，从而保证只会创建一个对象
                    //假设没有第二层检查，那么第一个线程创建完对象释放锁后，后面进入对象也会创建对象，会产生多个对象
                    if (instance == null) {//第二层检查
                        //volatile关键字作用为禁止指令重排，保证返回Singleton对象一定在创建对象后
                        //singleton=new Singleton语句为非原子性，实际上会执行以下内容：
                        //(1)在堆上开辟空间；(2)属性初始化;(3)引用指向对象
                        //volatile保证执行顺序
                        instance = new DoubleCheckSingleton();
                    }
                }
            }
            return instance;
    }
}



